﻿using System;
using Mono.Cecil.Metadata;
using Mono.Collections.Generic;

namespace Mono.Cecil
{
	// Token: 0x020000DE RID: 222
	public abstract class TypeSystem
	{
		// Token: 0x06000910 RID: 2320 RVA: 0x000054C5 File Offset: 0x000036C5
		private TypeSystem(ModuleDefinition module)
		{
			this.module = module;
		}

		// Token: 0x06000911 RID: 2321 RVA: 0x000274CC File Offset: 0x000256CC
		internal static TypeSystem CreateTypeSystem(ModuleDefinition module)
		{
			bool flag = module.IsCoreLibrary();
			TypeSystem result;
			if (flag)
			{
				result = new TypeSystem.CoreTypeSystem(module);
			}
			else
			{
				result = new TypeSystem.CommonTypeSystem(module);
			}
			return result;
		}

		// Token: 0x06000912 RID: 2322
		internal abstract TypeReference LookupType(string @namespace, string name);

		// Token: 0x06000913 RID: 2323 RVA: 0x000274F8 File Offset: 0x000256F8
		private TypeReference LookupSystemType(ref TypeReference reference, string name, ElementType element_type)
		{
			object syncRoot = this.module.SyncRoot;
			TypeReference result;
			lock (syncRoot)
			{
				bool flag2 = reference != null;
				if (flag2)
				{
					result = reference;
				}
				else
				{
					TypeReference typeReference = this.LookupType("System", name);
					typeReference.etype = element_type;
					TypeReference typeReference2;
					reference = (typeReference2 = typeReference);
					result = typeReference2;
				}
			}
			return result;
		}

		// Token: 0x06000914 RID: 2324 RVA: 0x0002756C File Offset: 0x0002576C
		private TypeReference LookupSystemValueType(ref TypeReference typeRef, string name, ElementType element_type)
		{
			object syncRoot = this.module.SyncRoot;
			TypeReference result;
			lock (syncRoot)
			{
				bool flag2 = typeRef != null;
				if (flag2)
				{
					result = typeRef;
				}
				else
				{
					TypeReference typeReference = this.LookupType("System", name);
					typeReference.etype = element_type;
					typeReference.KnownValueType();
					TypeReference typeReference2;
					typeRef = (typeReference2 = typeReference);
					result = typeReference2;
				}
			}
			return result;
		}

		// Token: 0x1700029F RID: 671
		// (get) Token: 0x06000915 RID: 2325 RVA: 0x000275E8 File Offset: 0x000257E8
		[Obsolete("Use CoreLibrary")]
		public IMetadataScope Corlib
		{
			get
			{
				return this.CoreLibrary;
			}
		}

		// Token: 0x170002A0 RID: 672
		// (get) Token: 0x06000916 RID: 2326 RVA: 0x00027600 File Offset: 0x00025800
		public IMetadataScope CoreLibrary
		{
			get
			{
				TypeSystem.CommonTypeSystem commonTypeSystem = this as TypeSystem.CommonTypeSystem;
				bool flag = commonTypeSystem == null;
				IMetadataScope coreLibraryReference;
				if (flag)
				{
					coreLibraryReference = this.module;
				}
				else
				{
					coreLibraryReference = commonTypeSystem.GetCoreLibraryReference();
				}
				return coreLibraryReference;
			}
		}

		// Token: 0x170002A1 RID: 673
		// (get) Token: 0x06000917 RID: 2327 RVA: 0x00027630 File Offset: 0x00025830
		public TypeReference Object
		{
			get
			{
				return this.type_object ?? this.LookupSystemType(ref this.type_object, "Object", ElementType.Object);
			}
		}

		// Token: 0x170002A2 RID: 674
		// (get) Token: 0x06000918 RID: 2328 RVA: 0x00027660 File Offset: 0x00025860
		public TypeReference Void
		{
			get
			{
				return this.type_void ?? this.LookupSystemType(ref this.type_void, "Void", ElementType.Void);
			}
		}

		// Token: 0x170002A3 RID: 675
		// (get) Token: 0x06000919 RID: 2329 RVA: 0x00027690 File Offset: 0x00025890
		public TypeReference Boolean
		{
			get
			{
				return this.type_bool ?? this.LookupSystemValueType(ref this.type_bool, "Boolean", ElementType.Boolean);
			}
		}

		// Token: 0x170002A4 RID: 676
		// (get) Token: 0x0600091A RID: 2330 RVA: 0x000276C0 File Offset: 0x000258C0
		public TypeReference Char
		{
			get
			{
				return this.type_char ?? this.LookupSystemValueType(ref this.type_char, "Char", ElementType.Char);
			}
		}

		// Token: 0x170002A5 RID: 677
		// (get) Token: 0x0600091B RID: 2331 RVA: 0x000276F0 File Offset: 0x000258F0
		public TypeReference SByte
		{
			get
			{
				return this.type_sbyte ?? this.LookupSystemValueType(ref this.type_sbyte, "SByte", ElementType.I1);
			}
		}

		// Token: 0x170002A6 RID: 678
		// (get) Token: 0x0600091C RID: 2332 RVA: 0x00027720 File Offset: 0x00025920
		public TypeReference Byte
		{
			get
			{
				return this.type_byte ?? this.LookupSystemValueType(ref this.type_byte, "Byte", ElementType.U1);
			}
		}

		// Token: 0x170002A7 RID: 679
		// (get) Token: 0x0600091D RID: 2333 RVA: 0x00027750 File Offset: 0x00025950
		public TypeReference Int16
		{
			get
			{
				return this.type_int16 ?? this.LookupSystemValueType(ref this.type_int16, "Int16", ElementType.I2);
			}
		}

		// Token: 0x170002A8 RID: 680
		// (get) Token: 0x0600091E RID: 2334 RVA: 0x00027780 File Offset: 0x00025980
		public TypeReference UInt16
		{
			get
			{
				return this.type_uint16 ?? this.LookupSystemValueType(ref this.type_uint16, "UInt16", ElementType.U2);
			}
		}

		// Token: 0x170002A9 RID: 681
		// (get) Token: 0x0600091F RID: 2335 RVA: 0x000277B0 File Offset: 0x000259B0
		public TypeReference Int32
		{
			get
			{
				return this.type_int32 ?? this.LookupSystemValueType(ref this.type_int32, "Int32", ElementType.I4);
			}
		}

		// Token: 0x170002AA RID: 682
		// (get) Token: 0x06000920 RID: 2336 RVA: 0x000277E0 File Offset: 0x000259E0
		public TypeReference UInt32
		{
			get
			{
				return this.type_uint32 ?? this.LookupSystemValueType(ref this.type_uint32, "UInt32", ElementType.U4);
			}
		}

		// Token: 0x170002AB RID: 683
		// (get) Token: 0x06000921 RID: 2337 RVA: 0x00027810 File Offset: 0x00025A10
		public TypeReference Int64
		{
			get
			{
				return this.type_int64 ?? this.LookupSystemValueType(ref this.type_int64, "Int64", ElementType.I8);
			}
		}

		// Token: 0x170002AC RID: 684
		// (get) Token: 0x06000922 RID: 2338 RVA: 0x00027840 File Offset: 0x00025A40
		public TypeReference UInt64
		{
			get
			{
				return this.type_uint64 ?? this.LookupSystemValueType(ref this.type_uint64, "UInt64", ElementType.U8);
			}
		}

		// Token: 0x170002AD RID: 685
		// (get) Token: 0x06000923 RID: 2339 RVA: 0x00027870 File Offset: 0x00025A70
		public TypeReference Single
		{
			get
			{
				return this.type_single ?? this.LookupSystemValueType(ref this.type_single, "Single", ElementType.R4);
			}
		}

		// Token: 0x170002AE RID: 686
		// (get) Token: 0x06000924 RID: 2340 RVA: 0x000278A0 File Offset: 0x00025AA0
		public TypeReference Double
		{
			get
			{
				return this.type_double ?? this.LookupSystemValueType(ref this.type_double, "Double", ElementType.R8);
			}
		}

		// Token: 0x170002AF RID: 687
		// (get) Token: 0x06000925 RID: 2341 RVA: 0x000278D0 File Offset: 0x00025AD0
		public TypeReference IntPtr
		{
			get
			{
				return this.type_intptr ?? this.LookupSystemValueType(ref this.type_intptr, "IntPtr", ElementType.I);
			}
		}

		// Token: 0x170002B0 RID: 688
		// (get) Token: 0x06000926 RID: 2342 RVA: 0x00027900 File Offset: 0x00025B00
		public TypeReference UIntPtr
		{
			get
			{
				return this.type_uintptr ?? this.LookupSystemValueType(ref this.type_uintptr, "UIntPtr", ElementType.U);
			}
		}

		// Token: 0x170002B1 RID: 689
		// (get) Token: 0x06000927 RID: 2343 RVA: 0x00027930 File Offset: 0x00025B30
		public TypeReference String
		{
			get
			{
				return this.type_string ?? this.LookupSystemType(ref this.type_string, "String", ElementType.String);
			}
		}

		// Token: 0x170002B2 RID: 690
		// (get) Token: 0x06000928 RID: 2344 RVA: 0x00027960 File Offset: 0x00025B60
		public TypeReference TypedReference
		{
			get
			{
				return this.type_typedref ?? this.LookupSystemValueType(ref this.type_typedref, "TypedReference", ElementType.TypedByRef);
			}
		}

		// Token: 0x04000379 RID: 889
		private readonly ModuleDefinition module;

		// Token: 0x0400037A RID: 890
		private TypeReference type_object;

		// Token: 0x0400037B RID: 891
		private TypeReference type_void;

		// Token: 0x0400037C RID: 892
		private TypeReference type_bool;

		// Token: 0x0400037D RID: 893
		private TypeReference type_char;

		// Token: 0x0400037E RID: 894
		private TypeReference type_sbyte;

		// Token: 0x0400037F RID: 895
		private TypeReference type_byte;

		// Token: 0x04000380 RID: 896
		private TypeReference type_int16;

		// Token: 0x04000381 RID: 897
		private TypeReference type_uint16;

		// Token: 0x04000382 RID: 898
		private TypeReference type_int32;

		// Token: 0x04000383 RID: 899
		private TypeReference type_uint32;

		// Token: 0x04000384 RID: 900
		private TypeReference type_int64;

		// Token: 0x04000385 RID: 901
		private TypeReference type_uint64;

		// Token: 0x04000386 RID: 902
		private TypeReference type_single;

		// Token: 0x04000387 RID: 903
		private TypeReference type_double;

		// Token: 0x04000388 RID: 904
		private TypeReference type_intptr;

		// Token: 0x04000389 RID: 905
		private TypeReference type_uintptr;

		// Token: 0x0400038A RID: 906
		private TypeReference type_string;

		// Token: 0x0400038B RID: 907
		private TypeReference type_typedref;

		// Token: 0x020000DF RID: 223
		private sealed class CoreTypeSystem : TypeSystem
		{
			// Token: 0x06000929 RID: 2345 RVA: 0x000054D6 File Offset: 0x000036D6
			public CoreTypeSystem(ModuleDefinition module) : base(module)
			{
			}

			// Token: 0x0600092A RID: 2346 RVA: 0x00027990 File Offset: 0x00025B90
			internal override TypeReference LookupType(string @namespace, string name)
			{
				TypeReference typeReference = this.LookupTypeDefinition(@namespace, name) ?? this.LookupTypeForwarded(@namespace, name);
				bool flag = typeReference != null;
				if (flag)
				{
					return typeReference;
				}
				throw new NotSupportedException();
			}

			// Token: 0x0600092B RID: 2347 RVA: 0x000279C8 File Offset: 0x00025BC8
			private TypeReference LookupTypeDefinition(string @namespace, string name)
			{
				MetadataSystem metadataSystem = this.module.MetadataSystem;
				bool flag = metadataSystem.Types == null;
				if (flag)
				{
					TypeSystem.CoreTypeSystem.Initialize(this.module.Types);
				}
				return this.module.Read<Row<string, string>, TypeDefinition>(new Row<string, string>(@namespace, name), delegate(Row<string, string> row, MetadataReader reader)
				{
					TypeDefinition[] types = reader.metadata.Types;
					for (int i = 0; i < types.Length; i++)
					{
						bool flag2 = types[i] == null;
						if (flag2)
						{
							types[i] = reader.GetTypeDefinition((uint)(i + 1));
						}
						TypeDefinition typeDefinition = types[i];
						bool flag3 = typeDefinition.Name == row.Col2 && typeDefinition.Namespace == row.Col1;
						if (flag3)
						{
							return typeDefinition;
						}
					}
					return null;
				});
			}

			// Token: 0x0600092C RID: 2348 RVA: 0x00027A38 File Offset: 0x00025C38
			private TypeReference LookupTypeForwarded(string @namespace, string name)
			{
				bool flag = !this.module.HasExportedTypes;
				TypeReference result;
				if (flag)
				{
					result = null;
				}
				else
				{
					Collection<ExportedType> exportedTypes = this.module.ExportedTypes;
					for (int i = 0; i < exportedTypes.Count; i++)
					{
						ExportedType exportedType = exportedTypes[i];
						bool flag2 = exportedType.Name == name && exportedType.Namespace == @namespace;
						if (flag2)
						{
							return exportedType.CreateReference();
						}
					}
					result = null;
				}
				return result;
			}

			// Token: 0x0600092D RID: 2349 RVA: 0x00002A20 File Offset: 0x00000C20
			private static void Initialize(object obj)
			{
			}
		}

		// Token: 0x020000E1 RID: 225
		private sealed class CommonTypeSystem : TypeSystem
		{
			// Token: 0x06000931 RID: 2353 RVA: 0x000054D6 File Offset: 0x000036D6
			public CommonTypeSystem(ModuleDefinition module) : base(module)
			{
			}

			// Token: 0x06000932 RID: 2354 RVA: 0x00027B44 File Offset: 0x00025D44
			internal override TypeReference LookupType(string @namespace, string name)
			{
				return this.CreateTypeReference(@namespace, name);
			}

			// Token: 0x06000933 RID: 2355 RVA: 0x00027B60 File Offset: 0x00025D60
			public AssemblyNameReference GetCoreLibraryReference()
			{
				bool flag = this.core_library != null;
				AssemblyNameReference result;
				if (flag)
				{
					result = this.core_library;
				}
				else
				{
					bool flag2 = this.module.TryGetCoreLibraryReference(out this.core_library);
					if (flag2)
					{
						result = this.core_library;
					}
					else
					{
						this.core_library = new AssemblyNameReference
						{
							Name = "mscorlib",
							Version = this.GetCorlibVersion(),
							PublicKeyToken = new byte[]
							{
								183,
								122,
								92,
								86,
								25,
								52,
								224,
								137
							}
						};
						this.module.AssemblyReferences.Add(this.core_library);
						result = this.core_library;
					}
				}
				return result;
			}

			// Token: 0x06000934 RID: 2356 RVA: 0x00027C04 File Offset: 0x00025E04
			private Version GetCorlibVersion()
			{
				Version result;
				switch (this.module.Runtime)
				{
				case TargetRuntime.Net_1_0:
				case TargetRuntime.Net_1_1:
					result = new Version(1, 0, 0, 0);
					break;
				case TargetRuntime.Net_2_0:
					result = new Version(2, 0, 0, 0);
					break;
				case TargetRuntime.Net_4_0:
					result = new Version(4, 0, 0, 0);
					break;
				default:
					throw new NotSupportedException();
				}
				return result;
			}

			// Token: 0x06000935 RID: 2357 RVA: 0x00027C64 File Offset: 0x00025E64
			private TypeReference CreateTypeReference(string @namespace, string name)
			{
				return new TypeReference(@namespace, name, this.module, this.GetCoreLibraryReference());
			}

			// Token: 0x0400038E RID: 910
			private AssemblyNameReference core_library;
		}
	}
}
